home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-M68K / SEMAPHOR.{2B < prev    next >
Text File  |  1999-09-17  |  4KB  |  169 lines

  1. #ifndef _M68K_SEMAPHORE_H
  2. #define _M68K_SEMAPHORE_H
  3.  
  4. #include <linux/config.h>
  5. #include <linux/linkage.h>
  6. #include <asm/current.h>
  7. #include <asm/system.h>
  8. #include <asm/atomic.h>
  9.  
  10. /*
  11.  * SMP- and interrupt-safe semaphores..
  12.  *
  13.  * (C) Copyright 1996 Linus Torvalds
  14.  *
  15.  * m68k version by Andreas Schwab
  16.  */
  17.  
  18. struct semaphore {
  19.     atomic_t count;
  20.     unsigned long owner, owner_depth;
  21.     atomic_t waking;
  22.     struct wait_queue * wait;
  23. };
  24.  
  25. /*
  26.  * Because we want the non-contention case to be
  27.  * fast, we save the stack pointer into the "owner"
  28.  * field, and to get the true task pointer we have
  29.  * to do the bit masking. That moves the masking
  30.  * operation into the slow path.
  31.  */
  32. #define semaphore_owner(sem) \
  33.     ((struct task_struct *)((2*PAGE_MASK) & (sem)->owner))
  34.  
  35. #define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, 0, ATOMIC_INIT(0), NULL })
  36. #define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, 1, ATOMIC_INIT(0), NULL })
  37.  
  38. asmlinkage void __down_failed(void /* special register calling convention */);
  39. asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
  40. asmlinkage void __up_wakeup(void /* special register calling convention */);
  41.  
  42. extern void __down(struct semaphore * sem);
  43. extern int  __down_interruptible(struct semaphore * sem);
  44. extern void __up(struct semaphore * sem);
  45.  
  46. #define sema_init(sem, val)    atomic_set(&((sem)->count), val)
  47.  
  48. static inline void wake_one_more(struct semaphore * sem)
  49. {
  50.     atomic_inc(&sem->waking);
  51. }
  52.  
  53. static inline int waking_non_zero(struct semaphore *sem, struct task_struct *tsk)
  54. {
  55. #ifndef CONFIG_RMW_INSNS
  56.     unsigned long flags;
  57.     int ret = 0;
  58.  
  59.     save_flags(flags);
  60.     cli();
  61.     if (atomic_read(&sem->waking) > 0 || (owner_depth && semaphore_owner(sem) == tsk)) {
  62.         sem->owner = (unsigned long)tsk;
  63.         sem->owner_depth++;
  64.         atomic_dec(&sem->waking);
  65.         ret = 1;
  66.     }
  67.     restore_flags(flags);
  68. #else
  69.     int ret, tmp;
  70.  
  71.     __asm__ __volatile__
  72.       ("1:    movel    %2,%0\n"
  73.        "    jeq    3f\n"
  74.        "2:    movel    %0,%1\n"
  75.        "    subql    #1,%1\n"
  76.        "    casl    %0,%1,%2\n"
  77.        "    jeq    3f\n"
  78.        "    tstl    %0\n"
  79.        "    jne    2b\n"
  80.        "3:"
  81.        : "=d" (ret), "=d" (tmp), "=m" (sem->waking));
  82.  
  83.     ret |= ((sem->owner_depth != 0) && (semaphore_owner(sem) == tsk));
  84.     if (ret) {
  85.         sem->owner = (unsigned long)tsk;
  86.         sem->owner_depth++;
  87.     }
  88.  
  89. #endif
  90.     return ret;
  91. }
  92.  
  93. /*
  94.  * This is ugly, but we want the default case to fall through.
  95.  * "down_failed" is a special asm handler that calls the C
  96.  * routine that actually waits. See arch/m68k/lib/semaphore.S
  97.  */
  98. extern inline void down(struct semaphore * sem)
  99. {
  100.     register struct semaphore *sem1 __asm__ ("%a1") = sem;
  101.     __asm__ __volatile__(
  102.         "| atomic down operation\n\t"
  103.         "subql #1,%0@\n\t"
  104.         "jmi 2f\n\t"
  105.         "movel %%sp,4(%0)\n"
  106.         "movel #1,8(%0)\n\t"
  107.         "1:\n"
  108.         ".section .text.lock,\"ax\"\n"
  109.         ".even\n"
  110.         "2:\tpea 1b\n\t"
  111.         "jbra __down_failed\n"
  112.         ".previous"
  113.         : /* no outputs */
  114.         : "a" (sem1)
  115.         : "memory");
  116. }
  117.  
  118. extern inline int down_interruptible(struct semaphore * sem)
  119. {
  120.     register struct semaphore *sem1 __asm__ ("%a1") = sem;
  121.     register int result __asm__ ("%d0");
  122.  
  123.     __asm__ __volatile__(
  124.         "| atomic interruptible down operation\n\t"
  125.         "subql #1,%1@\n\t"
  126.         "jmi 2f\n\t"
  127.         "movel %%sp,4(%1)\n"
  128.         "moveql #1,%0\n"
  129.         "movel %0,8(%1)\n"
  130.         "clrl %0\n"
  131.         "1:\n"
  132.         ".section .text.lock,\"ax\"\n"
  133.         ".even\n"
  134.         "2:\tpea 1b\n\t"
  135.         "jbra __down_failed_interruptible\n"
  136.         ".previous"
  137.         : "=d" (result)
  138.         : "a" (sem1)
  139.         : "%d0", "memory");
  140.     return result;
  141. }
  142.  
  143. /*
  144.  * Note! This is subtle. We jump to wake people up only if
  145.  * the semaphore was negative (== somebody was waiting on it).
  146.  * The default case (no contention) will result in NO
  147.  * jumps for both down() and up().
  148.  */
  149. extern inline void up(struct semaphore * sem)
  150. {
  151.     register struct semaphore *sem1 __asm__ ("%a1") = sem;
  152.     __asm__ __volatile__(
  153.         "| atomic up operation\n\t"
  154.         "subql #1,8(%0)\n\t"
  155.         "addql #1,%0@\n\t"
  156.         "jle 2f\n"
  157.         "1:\n"
  158.         ".section .text.lock,\"ax\"\n"
  159.         ".even\n"
  160.         "2:\tpea 1b\n\t"
  161.         "jbra __up_wakeup\n"
  162.         ".previous"
  163.         : /* no outputs */
  164.         : "a" (sem1)
  165.         : "memory");
  166. }
  167.  
  168. #endif
  169.